Frida 开发和调试环境搭建
前言
Frida 是一款开源的跨平台动态插桩工具,它可以在应用程序运行时注入自定义的 JavaScript 脚本,实现对函数调用的 Hook、参数修改、返回值篡改等操作。与 Xposed 不同,Frida 无需重启设备、无需安装框架,即插即用,且同时支持 Android、iOS、Windows、macOS 和 Linux 等多个平台。
在 Android 逆向工程中,Frida 已经成为最核心的动态分析工具之一。但要让 Frida 正常工作,首先需要搭建一个完整且版本匹配的开发和调试环境。本文将从零开始,带你完成 Frida 全套环境的搭建,并排除常见的坑。
1. Frida 环境准备
1.1 Python 环境安装
Frida 的命令行工具 frida-tools 基于 Python 开发,因此首先需要安装 Python 3.x 环境。
# 推荐使用 Python 3.8 ~ 3.12,避免使用最新版以兼容性问题
# 下载地址: https://www.python.org/downloads/
# Windows 安装时务必勾选 "Add Python to PATH"
安装完成后验证:
python --version
pip --version
提示:如果你使用 Python 3.10+,
pip可能需要显式调用为pip3。
1.2 安装 frida-tools
frida-tools 是 Frida 的官方命令行工具包,包含 frida、frida-ps、frida-trace 等常用命令:
pip install frida-tools
这会自动安装 frida-tools 及其依赖 frida(Python 绑定)。安装完成后验证:
frida --version
frida-ps --version
1.3 下载 frida-server
frida-server 是运行在 Android 设备端的守护进程,负责与 PC 端的 frida-tools 通信。它本质上是一个编译好的 ARM 原生可执行文件。
下载地址:https://github.com/frida/frida/releases
选择与 PC 端 frida-tools 版本号完全一致 的 release 包,根据设备 CPU 架构下载对应的文件:
| 设备架构 | 下载文件 | 适用设备 |
|---|---|---|
| arm64 | frida-server-{version}-android-arm64.xz |
大多数现代 Android 手机(模拟器一般选 x86) |
| arm | frida-server-{version}-android-arm.xz |
32 位 ARM 设备 |
| x86 | frida-server-{version}-android-x86.xz |
x86 模拟器 |
| x86_64 | frida-server-{version}-android-x86_64.xz |
x86_64 模拟器 |
查看设备架构:
adb shell getprop ro.product.cpu.abi
2. frida-server 部署到 Android 设备
2.1 推送 frida-server 到设备
# 解压下载的 .xz 文件后,将 frida-server 推送到设备
adb push frida-server /data/local/tmp/
# 进入 adb shell
adb shell
# 进入 frida-server 所在目录
cd /data/local/tmp/
# 赋予执行权限
chmod 755 frida-server
2.2 启动 frida-server
frida-server 必须以 root 权限 运行,因为 Frida 需要使用 ptrace 系统调用来注入目标进程:
# 方法一:前台运行(适合调试,Ctrl+C 可停止)
su -c /data/local/tmp/frida-server
# 方法二:后台运行(适合长期使用)
su -c /data/local/tmp/frida-server -D
注意:某些设备的
su命令可能不支持-c参数,此时可以进入 root shell 后直接运行:su /data/local/tmp/frida-server -D
2.3 验证连接
在 PC 端执行:
frida-ps -U
如果能列出 Android 设备上的进程列表,说明 frida-server 已正常工作。
3. USB 连接和无线连接
3.1 USB 连接
USB 是最常用的连接方式,稳定且延迟低:
# 1. 确认设备已通过 USB 连接并开启 USB 调试
adb devices
# 2. 启动 frida-server(见上文 2.2 节)
# 3. PC 端通过 -U 参数连接 USB 设备
frida-ps -U
frida -U -f com.example.app -l script.js
3.2 无线连接
无线连接适合不方便使用 USB 线的场景(如设备固定在支架上):
# 1. 先通过 USB 连接设备,获取设备 IP
adb shell ip addr show wlan0
# 或
adb shell ifconfig wlan0
# 2. 开启 TCP/IP 转发(需先 USB 连接)
adb tcpip 5555
# 3. 拔掉 USB 线,通过 IP 连接
adb connect 192.168.1.100:5555
# 4. 确认设备已连接
adb devices
# 5. frida 通过 -H 参数指定设备地址
frida-ps -H 192.168.1.100
frida -H 192.168.1.100 -f com.example.app -l script.js
注意:无线连接要求 PC 和手机在同一局域网内。首次连接必须通过 USB 执行
adb tcpip命令开启网络调试端口。
4. Frida 版本对应关系
Frida 环境搭建中最容易踩的坑就是版本不匹配。frida-tools(PC 端)和 frida-server(设备端)的版本号必须严格一致,否则会出现各种诡异错误。
┌─────────────────────┐ RPC ┌─────────────────────┐
│ PC 端 │ ◄──────────────► │ Android 设备端 │
│ │ │ │
│ frida-tools v16.x │ 协议必须匹配 │ frida-server v16.x │
│ frida (Python 绑定) │ │ (原生可执行文件) │
└─────────────────────┘ └─────────────────────┘
检查和同步版本的步骤:
# 查看 PC 端 frida 版本
frida --version
# 查看 frida-server 版本(设备端)
adb shell /data/local/tmp/frida-server --version
# 如果版本不一致,重新下载对应版本的 frida-server
安装指定版本的 frida-tools:
pip install frida-tools==12.3.0 frida==16.1.11
经验法则:每次更新 PC 端 frida-tools 后,务必同步更新设备端的 frida-server。建议将两个版本的检查作为日常调试前的例行步骤。
5. 常见环境问题排查
5.1 Root 权限不足
现象:frida-ps -U 提示 Failed to spawn: unable to find process 或 access denied。
排查:
# 确认 root 权限
adb shell su -c id
# 预期输出: uid=0(root) gid=0(root)
# 如果 su 不可用,说明设备未 root 或 root 方案有问题
# Magisk 设备检查:
adb shell magisk -v
5.2 SELinux 阻止
现象:frida-server 启动后立即退出,无报错信息。
排查:
# 查看 SELinux 状态
adb shell getenforce
# 如果输出 Enforcing,临时关闭:
adb shell su -c setenforce 0
永久关闭(仅限测试设备):编辑
/sys/fs/selinux/enforce或通过 Magisk 的 SELinux 模块处理。生产环境不建议永久关闭 SELinux。
5.3 端口冲突
现象:frida-ps -U 提示 Failed to attach 或连接超时。
排查:
# 检查 27042 端口是否被占用(Frida 默认端口)
adb shell netstat -tlnp | grep 27042
# 如果被占用,使用自定义端口启动 frida-server
su -c /data/local/tmp/frida-server -l 0.0.0.0:27043
# PC 端连接时指定端口
frida-ps -H 127.0.0.1:27043
5.4 版本不匹配
现象:PC 端报 Failed to spawn: invalid UUID 或 Protocol mismatch 等错误。
解决:严格按照第 4 节的方法同步两端版本。
5.5 一键排查脚本
将以下脚本保存为 frida-check.sh,用于快速排查环境问题:
#!/bin/bash
echo "=== Frida 环境检查 ==="
echo -n "[PC] frida-tools 版本: "
frida --version 2>/dev/null || echo "未安装"
echo -n "[设备] frida-server 版本: "
adb shell /data/local/tmp/frida-server --version 2>/dev/null || echo "未找到"
echo -n "[设备] Root 状态: "
adb shell su -c id 2>/dev/null || echo "无 root 权限"
echo -n "[设备] SELinux: "
adb shell getenforce 2>/dev/null
echo -n "[设备] CPU 架构: "
adb shell getprop ro.product.cpu.abi
echo "=== 检查完毕 ==="
6. PC 端工具安装
6.1 Python 绑定
frida-tools 安装时已自动包含 Python 绑定。你可以直接在 Python 脚本中使用:
import frida
# 列出 USB 设备上的进程
device = frida.get_usb_device()
processes = device.enumerate_processes()
for p in processes:
print(f"PID: {p.pid}, Name: {p.name}")
6.2 Node.js 绑定
如果你需要在 Node.js 环境中使用 Frida:
npm install frida
const frida = require('frida');
async function main() {
const device = await frida.getUsbDevice();
const processes = await device.enumerateProcesses();
processes.forEach(p => console.log(`PID: ${p.pid}, Name: ${p.name}`));
}
main().catch(console.error);
6.3 frida-tools CLI 工具集
frida-tools 提供了一组强大的命令行工具:
| 工具 | 用途 |
|---|---|
frida |
交互式 REPL 和脚本注入 |
frida-ps |
列出进程(类似 ps 命令) |
frida-trace |
跟踪函数调用 |
frida-discover |
自动发现内部函数 |
frida-kill |
终止进程 |
frida-ls-devices |
列出可用设备 |
7. IDE 配置推荐
7.1 VSCode + Frida 插件
VSCode 是编写 Frida 脚本的首选 IDE,推荐安装以下插件:
- Frida — 提供 Frida JavaScript API 的智能补全和语法高亮
- Python — Microsoft 官方 Python 插件,用于编写 Python 端控制脚本
- Prettier — 格式化 JavaScript 脚本
VSCode 的 tasks.json 配置示例(一键注入脚本):
{
"version": "2.0.0",
"tasks": [
{
"label": "Frida: 注入脚本",
"type": "shell",
"command": "frida",
"args": ["-U", "-f", "com.example.app", "-l", "${file}"],
"problemMatcher": []
}
]
}
7.2 PyCharm 调试配置
当你使用 Python 编写 Frida 控制脚本时,可以在 PyCharm 中直接调试:
import frida
import sys
def on_message(message, data):
if message['type'] == 'send':
print(f"[*] {message['payload']}")
elif message['type'] == 'error':
print(f"[!] {message['description']}")
# 连接 USB 设备
device = frida.get_usb_device()
# 附加到目标进程
session = device.attach("目标进程名")
# 加载脚本
with open("hook.js", "r", encoding="utf-8") as f:
script = session.create_script(f.read())
script.on("message", on_message)
script.load()
print("[*] 脚本已加载,按回车退出...")
sys.stdin.read()
在 PyCharm 中右键运行即可启动调试,支持断点调试 Python 逻辑。
8. 第一个 Frida 脚本
8.1 编写 Hook 脚本
创建 hook_android.js 文件:
// Hook android.widget.Toast 的 show 方法
Java.perform(function () {
var Toast = Java.use("android.widget.Toast");
// Hook show() 方法
Toast.show.overload().implementation = function () {
console.log("[*] Toast.show() 被调用!");
// 打印调用栈
console.log(Java.use("android.util.Log").getStackTraceString(
Java.use("java.lang.Exception").$new()
));
// 调用原始方法
this.show();
};
console.log("[*] Toast Hook 已生效");
});
8.2 运行脚本
# -U: USB 连接
# -f: 以 Spawn 模式启动应用(推荐,可在应用启动前注入)
# -l: 加载脚本文件
frida -U -f com.example.app -l hook_android.js --no-pause
如果应用已在运行,可以使用 Attach 模式:
# -n: 通过进程名附加
frida -U -n com.example.app -l hook_android.js
# -p: 通过 PID 附加
frida -U -p 12345 -l hook_android.js
9. 常用命令行参数详解
frida 命令的核心参数:
| 参数 | 全称 | 说明 |
|---|---|---|
-U |
--usb |
连接 USB 设备 |
-R |
--remote |
连接远程 frida-server |
-D |
--device |
指定设备 ID |
-H |
--host |
指定远程主机地址 |
-f |
--file |
Spawn 模式:启动应用并注入 |
-n |
--name |
Attach 模式:通过进程名附加 |
-p |
--pid |
Attach 模式:通过 PID 附加 |
-l |
--load |
加载 JavaScript 脚本 |
--no-pause |
— | Spawn 模式下自动恢复应用执行 |
-e |
--eval |
直接执行一段 JavaScript 代码 |
-o |
--output |
将输出重定向到文件 |
常用组合示例:
# Spawn 模式启动并注入(最常用)
frida -U -f com.target.app -l exploit.js --no-pause
# Attach 到正在运行的进程
frida -U -n "进程名" -l monitor.js
# 通过 IP 连接远程设备
frida -H 192.168.1.100:27042 -n "进程名" -l hook.js
# 直接执行单行代码
frida -U -f com.target.app -e "Java.perform(function(){ console.log('Hello Frida!'); })"
# 输出重定向到日志文件
frida -U -n "进程名" -l hook.js -o output.log
10. 实战案例:搭建完整环境并 Hook 系统 API
本节通过一个完整的案例,演示从环境搭建到成功 Hook 系统 API 的全过程。
10.1 目标分析
我们将 Hook android.os.Build 类的静态字段,在任意应用启动时读取并打印设备指纹信息。这个案例简单但实用,可以验证整个 Frida 环境是否正常工作。
10.2 编写脚本
创建 device_info.js:
Java.perform(function () {
var Build = Java.use("android.os.Build");
console.log("\n========== 设备指纹信息 ==========");
console.log(" Manufacturer : " + Build.MANUFACTURER.value);
console.log(" Model : " + Build.MODEL.value);
console.log(" Brand : " + Build.BRAND.value);
console.log(" SDK_INT : " + Build.VERSION.SDK_INT.value);
console.log(" Release : " + Build.VERSION.RELEASE.value);
console.log(" Fingerprint : " + Build.FINGERPRINT.value);
console.log("====================================\n");
// Hook getprop 流程 — 拦截 System.getProperty
var System = Java.use("java.lang.System");
System.getProperty.overload("java.lang.String").implementation = function (key) {
var result = this.getProperty(key);
console.log("[System.getProperty] " + key + " = " + result);
return result;
};
});
10.3 执行和验证
# 确认 frida-server 正在运行
adb shell "ps -A | grep frida-server"
# 如果未运行,启动它
adb shell "su -c /data/local/tmp/frida-server -D &"
# 等待 2 秒确保服务启动完成
sleep 2
# 列出设备进程确认连接正常
frida-ps -U | head -n 5
# Spawn 模式启动系统设置并注入
frida -U -f com.android.settings -l device_info.js --no-pause
预期输出:
[*] Spawned `com.android.settings`
========== 设备指纹信息 ==========
Manufacturer : Google
Model : Pixel 6
Brand : google
SDK_INT : 33
Release : 13
Fingerprint : google/oriole/oriole:13/TQ3A.230901.001/...
====================================
[System.getProperty] ro.build.version.sdk = 33
[System.getProperty] ro.product.model = Pixel 6
[System.getProperty] ro.product.manufacturer = Google
...
10.4 环境验证清单
当你看到上述输出时,说明以下所有环节均已正常:
- ✅ PC 端
frida-tools已正确安装 - ✅
frida-server版本与 PC 端匹配 - ✅ 设备已 root,frida-server 以 root 权限运行
- ✅ USB 连接正常或无线连接稳定
- ✅ JavaScript 注入引擎工作正常
- ✅ Java 层 Hook 功能正常
11. 总结
Frida 环境搭建看似步骤繁多,但核心只有三个要点:
- 版本一致:
frida-tools和frida-server版本号必须完全匹配 - Root 权限:frida-server 必须以 root 身份运行
- 网络通畅:PC 和设备之间的通信端口(默认 27042)不能被占用或阻断
掌握本文的内容后,你就拥有了 Frida 逆向分析的基础能力。后续我们将深入学习 Frida 的 Java 层 Hook、Native 层 Hook、以及反检测等高级技巧。
参考链接: